<script setup>
import { ref } from 'vue'
import { FileExcelRegular } from '@vicons/fa'
import ExcelJS from 'exceljs'
import { nanoid } from 'nanoid'
import { omit, set, compact } from 'lodash-es'
import { useMainStore } from '../pinia.js'

const mainStore = useMainStore()

const emit = defineEmits(['message'])

const uploadLoading = ref(false)

const taskList = ref([])

const handleXlsxUpload = async ({ file, onFinish }) => {
  const wb = new ExcelJS.Workbook()
  await wb.xlsx.load(await file.file.arrayBuffer())
  const ws = wb.getWorksheet(1)
  const tableData = {}
  ws.eachRow(row => {
    if (row.number !== 1 && row.getCell(4).text !== '') {
      set(tableData, [row.getCell(2).text, row.getCell(1).text], [row.getCell(3).text, row.getCell(4).text?.trim()])
    }
  })
  taskList.value.push({
    id: nanoid(),
    gpoNo: tableData['General']['Order/Enquiry No'][1].trim(),
    data: tableData
  })
  onFinish()
}

const clearTaskList = () => {
  taskList.value = []
}

const importLoading = ref(false)

const countryMap = [
  {
    from: ['CN', '中国'],
    to: 'China'
  },
  {
    from: ['JP', '日本'],
    to: 'Japan'
  },
  {
    from: ['USA', 'US', '美国'],
    to: 'United States'
  },
  {
    from: ['AU', '澳大利亚'],
    to: 'Australia'
  },
  {
    from: ['CA', '加拿大'],
    to: 'Canada'
  },
  {
    from: ['DE', '德国'],
    to: 'Germany'
  },
  {
    from: ['FR', '法国'],
    to: 'France'
  },
  {
    from: ['UK', '英国'],
    to: 'United Kingdom'
  }
]

// check a string if it is a country name list, if match after trim and tolowercase, return the English name
const checkCountry = (str) => {
  const splitedList = str.split(/[^a-zA-Z\s]+/).map(item => item.trim()).filter(item => item !== '')
  return compact(splitedList.map(splited => {
    for (const { from, to } of countryMap) {
      if (from.some(item => item.toLowerCase() === splited.toLowerCase()) || to.toLowerCase() === splited.toLowerCase()) return to
    }
    return splited
  })).join(',')
}

const determineCategory = (code) => {
  const orderPattern = /^\w{4}\d{10}\w{2}$/
  const enquiryPattern = /^\w{4}\d{10}\w{1}$/

  if (orderPattern.test(code)) {
    return 'order'
  } else if (enquiryPattern.test(code)) {
    return 'enquiry'
  } else {
    return 'unknown'
  }
}

const resolveTaskList = async () => {
  const checkCountryKey = ['CountryOfOrigin', 'CountryOfDestination']
  const checkReportLanguageKey = 'languageCode'
  const checkSameAsApplicantKey = 'sameAsApplicantFlag'

  importLoading.value = true
  for (const task of taskList.value) {
    try {
      task.status = 'processing'
      const data = task.data
      const newData = {}
      for (const category in data) {
        for (const key in data[category]) {
          switch (true) {
            case checkCountryKey.includes(key):
              set(newData, [category, key], checkCountry(data[category][key][1]))
              break
            case key === checkReportLanguageKey:{
              set(newData, ['Header', 'sameAsApplicantFlag'], 0)
              if (data[category][key][1] === 'English 英文') {
                set(newData, ['ReportInfo', 'reportLanguage'], '1')
                if (data?.['General']?.[checkSameAsApplicantKey]?.[1] === 'Applicant 申请方') {
                  set(newData, ['ReportInfo', 'reportHeader'], data?.['Applicant']?.['customerNameEn']?.[1])
                  set(newData, ['ReportInfo', 'reportDeliveredTo'], data?.['Applicant']?.['addressEn']?.[1])
                } else if (data?.['General']?.[checkSameAsApplicantKey]?.[1] === 'Payer 付款方') {
                  set(newData, ['ReportInfo', 'reportHeader'], data?.['Payer']?.['customerNameEn']?.[1])
                  set(newData, ['ReportInfo', 'reportDeliveredTo'], data?.['Payer']?.['addressEn']?.[1])
                } else if (data?.['General']?.[checkSameAsApplicantKey]?.[1] === 'Buyer 购买商') {
                  set(newData, ['ReportInfo', 'reportHeader'], data?.['Buyer']?.['customerNameEn']?.[1])
                  set(newData, ['ReportInfo', 'reportDeliveredTo'], data?.['Buyer']?.['addressEn']?.[1])
                }
              } else if (data[category][key][1] === 'Chinese 中文') {
                set(newData, ['ReportInfo', 'reportLanguage'], '2')
                if (data?.['General']?.[checkSameAsApplicantKey]?.[1] === 'Applicant 申请方') {
                  set(newData, ['ReportInfo', 'reportHeader'], data?.['Applicant']?.['customerNameCn']?.[1])
                  set(newData, ['ReportInfo', 'reportDeliveredTo'], data?.['Applicant']?.['addressCn']?.[1])
                } else if (data?.['General']?.[checkSameAsApplicantKey]?.[1] === 'Payer 付款方') {
                  set(newData, ['ReportInfo', 'reportHeader'], data?.['Payer']?.['customerNameCn']?.[1])
                  set(newData, ['ReportInfo', 'reportDeliveredTo'], data?.['Payer']?.['addressCn']?.[1])
                } else if (data?.['General']?.[checkSameAsApplicantKey]?.[1] === 'Buyer 购买商') {
                  set(newData, ['ReportInfo', 'reportHeader'], data?.['Buyer']?.['customerNameCn']?.[1])
                  set(newData, ['ReportInfo', 'reportDeliveredTo'], data?.['Buyer']?.['addressCn']?.[1])
                }
              }
              break
            }
            default:
              set(newData, [category, key], data[category][key][1])
              break
          }
        }
      }
      // transfer DFFGrid data to Array
      const DFFGridArray = [newData['DFFGrid']]
      newData['DFFGrid'] = DFFGridArray

      const type = determineCategory(task.gpoNo)
      const saveResult = await fetch('/data/updateGPODetail', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${mainStore.authToken}`
        },
        body: JSON.stringify({
          gpoNo: task.gpoNo,
          type,
          sgsToken: mainStore.sgsToken,
          data: omit(newData, ['General'])
        })
      }).then(res => res.json())
      if (saveResult.success) {
        task.status = 'success'
      } else {
        task.status = 'fail'
        console.log(saveResult)
        emit('message', 'error', saveResult.message)
      }
    } catch (error) {
      task.status = 'fail'
      emit('message', 'error', error.message)
    }
  }
  importLoading.value = false
}

</script>
<template>
  <n-grid x-gap="12" :cols="2">
    <n-gi :span="2" class="main-part">
      <n-spin :show="uploadLoading">
        <n-upload :show-file-list="false" :custom-request="handleXlsxUpload" accept=".xlsx" multiple>
          <n-upload-dragger>
            <div style="margin-bottom: 12px">
              <n-icon size="48" :depth="3">
                <FileExcelRegular />
              </n-icon>
            </div>
            <n-text style="font-size: 16px">
              点击上传或者拖动xlsx文件到该区域
            </n-text>
          </n-upload-dragger>
        </n-upload>
      </n-spin>
    </n-gi>
    <n-gi :span="2" class="main-part">
      <n-flex>
        <n-button type="primary" @click="resolveTaskList" :loading="importLoading">导入到GPO</n-button>
        <n-button type="primary" @click="clearTaskList">清空任务列表</n-button>
      </n-flex>
    </n-gi>
    <n-gi :span="2" class="main-part task-list">
      <n-flex :style="{ gap: 0 }">
        <n-thing v-for="task in taskList" :key="task.id" class="task-card">
          <template #avatar>
            <n-avatar>
              <n-icon>
                <FileExcelRegular />
              </n-icon>
            </n-avatar>
          </template>
          <template #header>
            {{ task.gpoNo }}
          </template>
          <template #header-extra>
            <n-tag type="success" v-if="task.status === 'success'">{{ task.status }}</n-tag>
            <n-tag type="error" v-else-if="task.status === 'fail'">{{ task.status }}</n-tag>
            <n-tag type="info" v-else>{{ task.status || 'ready' }}</n-tag>
          </template>
          <n-descriptions
            v-for="(group, category) in task.data"
            :title="category" label-placement="left" :column="2" bordered size="small" class="task-data-part"
          >
            <n-descriptions-item v-for="(value, key) in group">
              <template #label>
                {{ value[0] }}
              </template>
              {{ value[1] }}
            </n-descriptions-item>
          </n-descriptions>
        </n-thing>
      </n-flex>
    </n-gi>
  </n-grid>
</template>

<style lang="stylus">
.main-part
  margin-bottom: 10px
.task-list
  height: calc(100vh - 256px)
  overflow-y: auto
  .task-card
    border: solid 1px #e9e9e9
    border-radius: 4px
    padding: 10px
    width: 48%
    display: inline-block
    margin: 2px
    .task-data-part
      margin-bottom: 10px
</style>